﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cassini;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting.Channels;
using QualityStormCommon;
using System.Web.Security;
namespace QualityStormServer {
    class Program {
        private static Server webServer;
        private static QualityStormEntities db = new QualityStormEntities();
        
        static void Main(string[] args) {
            PrintStartupMessages();
            LoadConfig();
            StartWebserver();
            StartScheduler();
            StartObjectServer();
            StartCommandPrompt();
            
        }

        private static void StartObjectServer() {
            Print("Starting Object Server on Port " + QualityStormCommon.ServerConfiguration.ObjectServerPort.ToString());
            try {
                TcpChannel channel = new TcpChannel(QualityStormCommon.ServerConfiguration.ObjectServerPort);
                ChannelServices.RegisterChannel(channel);
                RemotingConfiguration.RegisterWellKnownServiceType(
                   typeof(QualityStormCommon.QualityStormService), "QualityStormService",
                   WellKnownObjectMode.Singleton);

            } catch (Exception e) {
                Print(e.Message);
            }

            
            

        }

        private static void StartCommandPrompt() {
            GetAdminPassword();
            System.Console.WriteLine("");
            Print("Admin Password Accepted, starting command prompt.");
            System.Console.WriteLine("\n---------------------------");
            System.Console.WriteLine("QualityStorm Command Prompt");
            System.Console.WriteLine("---------------------------");
            System.Console.WriteLine("Type 'help' for commands instructions.\n");

            string cmd = "";
            while (cmd.ToUpper() != "QUIT") {
               
                System.Console.Write("# ");
                cmd= System.Console.ReadLine();
                // Create User Command

                if (IsCommand(cmd, "CREATEUSER")) {
                    ProcessCreateUser(cmd);
                }

                if (IsCommand(cmd, "CREATEROLE")) {
                    ProcessCreateRole(cmd);
                }
                if (IsCommand(cmd, "SHOWUSERS")) {
                    ShowUsers();
                }

                if (IsCommand(cmd, "SETPASSWORD")) {
                    ProcessSetPassword(cmd);
                }

                if (IsCommand(cmd, "UNLOCKUSER")) {
                    
                }

                if (IsCommand(cmd, "SETPASSWORD")) {
                    
                }

                if (IsCommand(cmd, "HELP")) {
                    ShowHelp();
                }

                if (IsCommand(cmd, "SHOWFOLDERS")) {
                    foreach (Folder folder in db.Folders) {
                        System.Console.WriteLine(folder.Name);
                    }
                }
            }
        }

        private static void ProcessCreateRole(string cmd) {
            throw new NotImplementedException();
        }

        private static void ShowHelp() {
            System.Console.WriteLine("Available Commands:");
            System.Console.WriteLine("-------------------");
            System.Console.WriteLine("CREATEUSER");
            System.Console.WriteLine("SHOWUSERS");
            System.Console.WriteLine("SETPASSWORD");
            System.Console.WriteLine("QUIT");
        }

        private static void ProcessSetPassword(string cmd) {
            string[] cmds = cmd.Split(new char[] {' '});
            if (cmds.Length < 3) {
                Error("Wrong number of parameters.\n Type 'help' for commands instructions");
                return;
            } else {
                string login = cmds[1];
                string password = FormsAuthentication.HashPasswordForStoringInConfigFile(cmds[2], "SHA1");
                var users = from user in db.Users.Where("it.Login=='" + login + "'") select user;
                bool found = false;
                foreach (User user in users) {
                    user.Password = password;
                    db.SaveChanges();
                    System.Console.WriteLine("Password successfully changed.");
                    found = true;
                }
                if (!found) {
                    Error("User " + login + " Not found.");
                }


            }

        }

        private static void ShowUsers() {
            var users = from user in db.Users
                        select user;

            System.Console.WriteLine("Login");
            System.Console.WriteLine("--------------------");


            foreach (User user in users) {
                System.Console.WriteLine(user.Login);
            }
        }

        private static void ProcessCreateUser(string cmd) {
            string[] cmds = cmd.Split(new char[] { ' ' });
            if (cmds.Length < 2) {
                Error("Wrong number of parameters.\n Type 'help' for commands instructions");
                return;
            } else {
               //  Check if there is another user with the same login;
                string login = cmds[1];
                var users = from user in db.Users.Where("it.Login == '" + login + "'") select user;

                bool found = false;
                foreach (User user in users) {
                    found = true;
                }

                if (found) {
                    Error("User '" + cmds[1] + "' already created.");
                } else {
                    User newUser = User.CreateUser(Guid.NewGuid());
                    newUser.Login = cmds[1];
                    if (cmds.Length > 2) {
                        newUser.Password = FormsAuthentication.HashPasswordForStoringInConfigFile(cmds[2], "SHA1");
                        db.AddToUsers(newUser);
                        db.SaveChanges();
                        System.Console.WriteLine("User successfuly created.");
                    }
                }
            }

            
        }

        private static void Error(string p) {
            System.Console.WriteLine("Command Error: " + p);
        }

        private static bool IsCommand(string cmd, string testingCmd) {
            if (cmd.Length < testingCmd.Length)
                return false;

            return cmd.ToUpper().Substring(0, testingCmd.Length) == testingCmd;
        }

        private static void GetAdminPassword() {
            bool exit = false;
            string password = "";
            System.Console.Write("\nAdmin Password: ");
            while (!exit) {
                ConsoleKeyInfo key = Console.ReadKey(true);
                
                if (key.Key != ConsoleKey.Enter) {
                    System.Console.Write("*");
                    password = password + key.KeyChar;
                } else {
                    if (password=="admin") {
                        exit = true;
                    } else {
                        System.Console.Write("\nAdmin Password: ");
                        password = "";
                        exit = false;
                    }
                }
            }
            
        }

        private static void StartScheduler() {
            Print("Starting Scheduler");
        }

        private static void StartWebserver() {
            Print("Starting Embedded Webserver on Port " + QualityStormCommon.ServerConfiguration.WebserverPort.ToString());
            webServer = new Server(QualityStormCommon.ServerConfiguration.WebserverPort, "\\", System.IO.Path.GetDirectoryName( System.Windows.Forms.Application.ExecutablePath));
            try {
                webServer.Start();
            } catch (Exception e) {
                Print(e.Message);
            }
        }

        private static void Print(string p) {
            System.Console.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + "] " + p);
        }

        private static void PrintStartupMessages() {
            System.Console.Title = "QualityStorm Server";
            
            System.Console.WriteLine("QualityStorm Server Version 0.0001");
            
        } 

        private static void LoadConfig() {
            Print("Loading Configuration");
        }
        
    }
}
